package io.cici.cc.mybatis.lite.reflection.factory;

import io.cici.cc.mybatis.lite.util.SecurityManagerUtil;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.*;


public class ObjectFactoryImpl implements ObjectFactory, Serializable {

    private static final long serialVersionUID = -8855120656740914948L;

    @Override
    public <T> T create(Class<T> type) {
        try {
            Class<?> classToCreate = getInterfaceImpl(type);
            Constructor<T> constructor = (Constructor<T>) classToCreate.getDeclaredConstructor();
            try {
                return constructor.newInstance();
            } catch (IllegalAccessException e) {
                if (SecurityManagerUtil.memberAccessibleControl()) {
                    constructor.setAccessible(true);
                    return constructor.newInstance();
                }
                throw e;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected Class<?> getInterfaceImpl(Class<?> type) {
        Class<?> classToCreate;
        if (type == List.class || type == Collection.class || type == Iterable.class) {
            classToCreate = ArrayList.class;
        } else if (type == Map.class) {
            classToCreate = HashMap.class;
        } else if (type == Set.class) {
            classToCreate = HashSet.class;
        } else if (type == SortedSet.class) {
            classToCreate = TreeSet.class;
        } else {
            classToCreate = type;
        }
        return classToCreate;
    }

    @Override
    public <T> boolean isCollection(Class<T> type) {
        return Collection.class.isAssignableFrom(type);
    }

}
